package com.geeke.wf.controller;

import java.util.List;

import org.camunda.bpm.engine.RepositoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.migration.MigrationPlan;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.task.TaskQuery;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.geeke.common.controller.BaseController;
import com.geeke.utils.ResultUtil;
import com.geeke.utils.SessionUtils;
import com.geeke.utils.StringUtils;
import com.geeke.utils.constants.ErrorEnum;
import com.geeke.wf.service.WfUtils;


/**
 * 流程实例 Controller
 * @author lys
 * @version 2020-04-30
 */
@RestController
@RequestMapping(value = "/wf/task")
public class TaskController extends BaseController {

	@Autowired
	private TaskService taskService;

	@Autowired
	private RepositoryService repositoryService;

	@Autowired
	private RuntimeService runtimeService;

	@Autowired
	protected WfUtils<?> wfUtils;

	/**
	 * 签收任务
	 * @param taskId
	 * @return
	 */
	@GetMapping("claim/{taskId}")
	public ResponseEntity<JSONObject> claim(@PathVariable("taskId") String taskId) {
		wfUtils.claim(taskId);
		return ResponseEntity.ok(ResultUtil.successJson("claim success")); 
	}

    /**
     * 获取人员指派任务和候选任务
     * @param descriptionLike
     * @param sortBy
     * @param sortOrder
     * @param firstResult
     * @param maxResults
     * @return
     */
    @GetMapping("/page")  
    public ResponseEntity<JSONObject> listPage(
		@RequestParam(value = "descriptionLike", required = false) String descriptionLike,
		@RequestParam("sortBy") String sortBy,
		@RequestParam("sortOrder") String sortOrder,
		@RequestParam("firstResult") int firstResult,
		@RequestParam("maxResults") int maxResults
	){
		// 任务限定在当前登录用户
		String assignee = SessionUtils.getUser().getId();

		TaskQuery taskQuery = taskService.createTaskQuery().or().taskAssignee(assignee).taskCandidateUser(assignee).endOr();
		if(StringUtils.isNotBlank(descriptionLike)) {
		 	taskQuery.taskDescriptionLike(descriptionLike);
		}
		
		long total = taskQuery.count();

		if(StringUtils.isNotBlank(sortBy) && StringUtils.isNotBlank(sortOrder)) {
			if("dueDate".equals(sortBy)) {
				taskQuery.orderByDueDate();
		   	} else if("description".equals(sortBy)) {
			   taskQuery.orderByTaskDescription();
		   	} else if("name".equals(sortBy)) {
			   taskQuery.orderByTaskName();
		   	} else if("priority".equals(sortBy)) {
			   taskQuery.orderByTaskPriority();
		   	} else if("created".equals(sortBy)) {
			   taskQuery.orderByTaskCreateTime();
		   	}
   
		   	if("desc".equalsIgnoreCase(sortOrder)) {
			   taskQuery.desc();
		   	} else if("asc".equalsIgnoreCase(sortOrder)) {
			   taskQuery.asc();
		   	}
		} else {
			// 默认按优先级降序，创建时间升序排序 
		    taskQuery.orderByTaskPriority().desc().orderByTaskCreateTime().asc();
		}

		List<Task>  tasks = taskQuery.initializeFormKeys().listPage(firstResult, maxResults);
		JSONArray jsonArr = new JSONArray();
		if(tasks != null) {
			for(Task task: tasks) {
				jsonArr.add(getTaskJson(task));
			}
		}
		
		JSONObject jsonResult = new JSONObject();
		jsonResult.put("total", total);
		jsonResult.put("rows", jsonArr);		
		return ResponseEntity.ok(ResultUtil.successJson(jsonResult)); 
    }
    

    /**
     * 获取历史版本的在途任务
     * @param definitionKey
     * @return
     */
    @GetMapping("/oldversion/{definitionKey}")  
    public ResponseEntity<JSONObject> listOldVersion(
		@PathVariable("definitionKey") String definitionKey,
		@RequestParam(value = "description" , required = false) String description,	// 标题
		@RequestParam(value = "applyee", required = false) String applyee,			// 申请人
		@RequestParam(value = "approver", required = false) String approver,		// 审批人
		@RequestParam(value = "sortBy", required = false) String sortBy,				// 排序字段
		@RequestParam(value = "sortOrder", required = false) String sortOrder		// 排序顺序
	){
		JSONArray jsonArr = new JSONArray();
		List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery().processDefinitionKey(definitionKey).orderByProcessDefinitionId().asc().list();
		if(processDefinitions == null || processDefinitions.size() <= 1) {
		    return ResponseEntity.ok(ResultUtil.successJson(jsonArr)); 
		}

		TaskQuery taskQuery = taskService.createTaskQuery().or();
		// 去掉最新的流程定义版本
		for(int i = 0; i< processDefinitions.size() - 1; i++) {
		    ProcessDefinition processDefinition = processDefinitions.get(i);
			taskQuery = taskQuery.processDefinitionId(processDefinition.getId());
		}
		taskQuery = taskQuery.endOr();
		
		if(StringUtils.isNotBlank(description)) {
			taskQuery = taskQuery.taskDescriptionLike("%\"desc\":\"%" + description + "%\",\"proc\"%");
		}
		if(StringUtils.isNotBlank(applyee)) {
			taskQuery = taskQuery.taskDescriptionLike("%\"applicantName\":\"%" + applyee + "%\",\"approverId\"%");
		}
		if(StringUtils.isNotBlank(approver)) {
			taskQuery = taskQuery.taskDescriptionLike("%\"approverName\":\"%" + approver + "%\",\"ownerId\"%");
		}
		if(StringUtils.isNotBlank(sortBy) && StringUtils.isNotBlank(sortOrder)) {
			if("extInfo.desc".equals(sortBy)) {
				taskQuery = taskQuery.orderByTaskDescription();
			} else if("created".equals(sortBy)) {
			    taskQuery = taskQuery.orderByTaskCreateTime();
			} else if("name".equals(sortBy)) {
			    taskQuery = taskQuery.orderByTaskName();
			}
			if("descending".equals(sortOrder)) {
				taskQuery = taskQuery.desc();
			} else {
				taskQuery = taskQuery.asc();
			}
		} else {
		    taskQuery = taskQuery.orderByTaskDescription().asc();
		}

		List<Task> tasks = taskQuery.list();
		if(tasks != null) {
			for(Task task: tasks) {
				jsonArr.add(getTaskJson(task, false));
			}
		}
		return ResponseEntity.ok(ResultUtil.successJson(jsonArr)); 
    }

    /**
     * 升级任务到最新的流程版本
     * @param definitionKey
     * @return
     */
    @GetMapping("/upgrade/{taskId}")  
    public ResponseEntity<JSONObject> Upgrade(
		@PathVariable("taskId") String taskId
	){
		try {
			Task task =taskService.createTaskQuery().taskId(taskId).singleResult();

			// 获取任务流程定义
			ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(task.getProcessDefinitionId()).singleResult();
	
			// 获取最新版本的流程定义
			ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().processDefinitionKey(processDefinition.getKey());
			if(StringUtils.isNotBlank(processDefinition.getTenantId())) {
				processDefinitionQuery.tenantIdIn(processDefinition.getTenantId());
			} else {
				processDefinitionQuery.withoutTenantId();
			}
			ProcessDefinition latestProcessDefinition = processDefinitionQuery.latestVersion().singleResult();
	
			//	指定迁移计划
			MigrationPlan migrationPlan = runtimeService.createMigrationPlan(processDefinition.getId(), latestProcessDefinition.getId())
				.mapEqualActivities()
				.build();
	
			// 执行迁移
			runtimeService.newMigration(migrationPlan).processInstanceIds(task.getProcessInstanceId())
				.skipCustomListeners()
				.skipIoMappings()
				.execute();
	
			return ResponseEntity.ok(ResultUtil.successJson("任务流程升级成功。")); 
		} catch (Exception e) {
			e.printStackTrace();
		}
		return ResponseEntity.ok(ResultUtil.errorJson(ErrorEnum.E_30001, "任务流程升级失败。"));
	}
	
	
	/**
	 * 生成Task JSON
	 * @param task
	 * @return
	 */
	private JSONObject getTaskJson(Task task) {
		return getTaskJson(task, true);
	}

	private JSONObject getTaskJson(Task task, boolean isFormKeyInitialized) {
	    JSONObject jsonObj = new JSONObject();
		jsonObj.put("id", task.getId());
		jsonObj.put("name", task.getName());
		jsonObj.put("assignee", task.getAssignee());
		jsonObj.put("created", task.getCreateTime());
		jsonObj.put("due", task.getDueDate());
		jsonObj.put("followUp", task.getFollowUpDate());
		jsonObj.put("delegationState", task.getDelegationState());
		jsonObj.put("description", task.getDescription());
		jsonObj.put("executionId", task.getExecutionId());
		jsonObj.put("owner", task.getOwner());
		jsonObj.put("parentTaskId", task.getParentTaskId());
		jsonObj.put("priority", task.getPriority());
		jsonObj.put("processDefinitionId", task.getProcessDefinitionId());
		jsonObj.put("processInstanceId", task.getProcessInstanceId());
		jsonObj.put("taskDefinitionKey", task.getTaskDefinitionKey());
		jsonObj.put("caseExecutionId", task.getCaseExecutionId());
		jsonObj.put("caseInstanceId", task.getCaseInstanceId());
		jsonObj.put("caseDefinitionId", task.getCaseDefinitionId());
		jsonObj.put("suspended", task.isSuspended());
		jsonObj.put("tenantId", task.getTenantId());
		if(isFormKeyInitialized) {
			jsonObj.put("formKey", task.getFormKey());
		}

		return jsonObj;
	}
}